#ifndef ATTRS_H
#define ATTRS_H

#include <string>
#include <vector>

using std::vector;
using std::string;

// 可能需要修改的常量：特别注意IP ！！
const uint32_t THREAD_NUMS  = 40;
const uint32_t MAX_SLOT     = 6020;
const uint32_t TCP          = 6;
const uint32_t UDP          = 17;
const uint64_t MS_TO_NS     = 1000000ULL;
const uint64_t S_TO_NS      = 1000000000ULL;

const string OVS_QDISC      = "ATS";
const string OVS_DPDK       = "ovsdpdk";

const string OVS_DPDK_MPLS  = "ovsdpdk-db4";
/* ********************** Topo Redis ******************************* */
const string REDIS_TOPO     = "tcp://121.48.163.229";//183
const string REDIS_PASSWD   = "uEstC318.#";
const string TOPOLOGY_KEY   = "all_links";

/* ********************* Measure Redis ***************************** */
const string REDIS_MEASURE  = "tcp://121.48.163.228";//155
const string FLOW_DELAY     = "FLOWS-LATEST-DELAY";
const string CURRENT_SLOT   = "CURRENT-SLOT";

/* ********************** ONOS Request ***************************** */
const string ONOS_HOST      = "http://121.48.163.228:18181";//155
const string ONOS_PATH      = "/onos/v1/flows?appId=org.onosproject.core";
const string content_type   = "application/json";
const string CONTROLLER_IP  = "172.17.0.2";

/* ********************** Route Request ***************************** */
const string ROUTE_HOST     = "http://121.48.163.229:8888";//183
const string ROUTING_PATH   = "/get-routing?srcSatellite={}&dstSatellite={}&isDisjoint=false"; 
const string STATION_PATH   = "/get-station-routing?src={}&dst={}";
const string CLEAR_CACHE    = "/clear-flow-cache";
const string DYNAMIC_ROUTING  = "/get-dynamic-routing?srcSatellite={}&dstSatellite={}&slot={}&tos={}";

// CLB-DT-DVTR routing
const string ROUTING_TOS_PATH = "/get-routing?srcSatellite={}&dstSatellite={}&isDisjoint=false&tos={}";
// TGM routing
// const string ROUTING_TOS_PATH = "/get-tgm-routing?srcSatellite={}&dstSatellite={}&isDisjoint=false&tos={}";
// DT-DVTR routing
// const string ROUTING_TOS_PATH = "/get-dt-dvtr-routing?srcSatellite={}&dstSatellite={}&isDisjoint=false&tos={}";

const string STATION_TOS_PATH = "/get-station-routing?src={}&dst={}&tos={}";

// CLB-DT-DVTR routing + 业务带宽
const string ROUTING_TOS_PATH_CHANGE = "/get-routing-change?srcSatellite={}&dstSatellite={}&isDisjoint=false&tos={}&demand={}";

// 添加分离路由的路由请求方法
const string DisROUTING_TOS_PATH = "/get-routing?srcSatellite={}&dstSatellite={}&isDisjoint=true&tos={}";

/* ********************** Flow Related ***************************** */
const string FLOW_ID        = "{}-{}-{}-{}";       // 1101-1601-2-0
const string FLOW_E2E_DELAY = "{}-{}-{}-ALL";   // 1101-1601-2-ALL
const string IP_ADDR        = "192.168.{}.{}";
const string MAC_ADDR       = "00:00:00:00:{}:{}";

/* 注意修改此处FILE NAME后，下面某些用到该文件的地方可能也要修改 */
/* ********************** FILE NAME ***************************** */
const string LINK_FILE      = "/root/scripts/link/s{}_link_update";
const string DOCKER_LOGFILE = "/root/logfile/link/s{}_link.log";
const string VETH_PAIR_FILE = "/root/scripts/set_veth_peer.sh";
const string OVS_INIT_FILE  = "/root/scripts/ovs/s{}_init_ovs.sh";

/* ********************** OVS COMMAND ***************************** */
const string OVS_ADD_PORT   = "ovs-vsctl add-port s{0} {1} -- set Interface {1} ofport_request={2};";
const string OVS_DEL_PORT   = "ovs-vsctl del-port {0};";
const string OVS_SET_QDISC  =  "ovs-vsctl set interface {0} other_config:qdisc={1};";


// ovs-vsctl set interface 1101-1102 other_config:qdisc-params="rate:1=10000,2=20000,3=30000,4=40000,5=50000,6=60000,7=70000";
// ovs-vsctl set interface 1102-1102 other_config:qdisc-params="bucketsize:1=10000,2=20000,3=30000,4=40000,5=50000,6=60000,7=70000";
const string CHANGE_DELAY   = "tc qdisc change dev {0} root netem delay {1} limit 20000;";

/* ********************** EXECUTE COMMAND ***************************** */
const string CMD_SET_ARP        = "docker exec -it s{0} bash /root/scripts/arp.sh > /dev/null";
const string CMD_SET_VETH_PAIR  = "sh " + VETH_PAIR_FILE;
const string CMD_RUN_IN_DOCKER  = "docker exec -d s{0} /root/scripts/docker_run {0} {1} &";
const string CMD_USER_SEND      = "docker exec s{0} /usr/bin/user_send > /root/logfile/s{0}_send.log 2>&1 &";
const string CMD_USER_RECV      = "docker exec s{0} /usr/bin/user_recv > /root/logfile/s{0}_recv.log 2>&1 &";
const string CMD_BAND           = "docker exec s{0} /usr/bin/band > /root/logfile/s{0}_band.log 2>&1 &";

//  const string CMD_FLOW = "docker exec s{0} bash -c \"ovs-ofctl add-flow s{0} \\\"priority=40010,ip,nw_src={2},nw_dst={3},actions=mod_nw_tos:7,output:{1}\\\" \"";

//  const string CMD_FLOW =  "ovs-ofctl add-flow s{0} \"priority=40010,ip,nw_src={2},nw_dst={3},actions=mod_nw_tos:7,output:{0}-{1}\" ";


/* 0: device id, 1: docker image */
const string CMD_CREATE_DOCKER  =
R"(docker create -it --name=s{0} --privileged \
    -v /dev/hugepages:/dev/hugepages \
    -v /root/logfile:/root/logfile \
    -v /root/scripts:/root/scripts {1} > /dev/null;
docker start s{0} > /dev/null;
docker exec -it s{0} /bin/bash /root/scripts/ovs/s{0}_init_ovs.sh > /dev/null;
)";
// dpdk-hugepages.py -p 1G --setup 4G
// modprobe openvswitch
// docker create -it --name=s1101 --privileged -v /dev/hugepages:/dev/hugepages -v /root/logfile:/root/logfile -v /root/scripts:/root/scripts ovsdpdk-db4 > /dev/null;
// docker start s1101 > /dev/null;
// docker exec -it s1101 /bin/bash /root/scripts/ovs/s1101_init_ovs.sh ;

/* 0: 1101, 1: 1102 */
const string CMD_CREATE_VETH_PAIR =
R"(
#创建 veth pair ，将标准输出重定向到空设备，以忽略输出信息。
ip link add {0}-{1} type veth peer name {1}-{0} > /dev/null
#将 veth pair 的一端移入相应的 Docker 容器网络命名空间，并设置为 UP 状态。
ip link set dev {0}-{1} name {0}-{1} netns $(sudo docker inspect -f '{{{{.State.Pid}}}}' s{0}) up
ip link set dev {1}-{0} name {1}-{0} netns $(sudo docker inspect -f '{{{{.State.Pid}}}}' s{1}) up
#在 Docker 容器 s{0} 中的 veth pair 上添加网络延迟的队列规则
docker exec s{0} tc qdisc add dev {0}-{1} root netem delay 1
docker exec s{1} tc qdisc add dev {1}-{0} root netem delay 1
)";

/* 0: core id, 1: node_id, 2: mac, 3: ip, 4: controller_ip  */
const string CMD_START_OVS =
R"(
# 创建数据库文件
mkdir -p /usr/local/etc/openvswitch
ovsdb-tool create /usr/local/etc/openvswitch/conf.db \
    /usr/local/share/openvswitch/vswitch.ovsschema

# 启动数据库
mkdir -p /usr/local/var/run/openvswitch
mkdir -p /usr/local/var/log/openvswitch
ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \
    --remote=db:Open_vSwitch,Open_vSwitch,manager_options \
    --private-key=db:Open_vSwitch,SSL,private_key \
    --certificate=db:Open_vSwitch,SSL,certificate \
    --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \
    --pidfile --detach --log-file

# 初始化数据库
ovs-vsctl --no-wait init

# 配置使用DPDK, pmd-cpu-mask 要用16进制
ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask={0}
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-socket-mem="1024"
ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-init=true

# 启动 Open vSwitch 守护进程
ovs-vswitchd --pidfile --detach --log-file=/root/logfile/s{1}-vswitchd.log

# 创建 bridge, 并为本地端口配置ip地址
ovs-vsctl add-br s{1} -- set bridge s{1} datapath_type=netdev
ovs-vsctl set bridge s{1} other_config:datapath-id=0x000000000000{1}
ovs-vsctl set bridge s{1} other_config:hwaddr="{2}"
ifconfig s{1} {3} netmask 255.255.0.0 up
# route add default dev s{1}

# 设置 openflow, 才可连接ONOS控制器, 只能用OpenFlow13
ovs-vsctl set bridge s{1} protocols=OpenFlow10,OpenFlow13
ovs-vsctl set-controller s{1} tcp:{4}:6653
)";


uint64_t get_time_ns(void)
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    return ts.tv_sec * S_TO_NS + ts.tv_nsec;
}

vector<string> split(const string &str, char c)
{
    vector<string> res;
    string tmp = "";

    for (const char &s : str) {
        if (s == c) {
            if (!tmp.empty())
                res.push_back(tmp);
            tmp = "";
        } else
            tmp += s;
    }
    if (!tmp.empty())
        res.push_back(tmp);
    return res;
}

/* 流表模板 */
namespace rules {

const string BATCH_RULES = R"({{"flows": [{0}]}})";

/* ************************************************************************ */
/* ****************************** IP FLOW ********************************* */
/* ************************************************************************ */

/* 流表优先级：
 * 40000, ONOS默认流表
 * 40010，只按IP转发
 * 40011，按IP转发，且设置了超时时间
 * 40020，涉及到MPLS
 * 40021，涉及到MPLS，且设置了超时时间
 * 
 */

/* 起始节点和中间节点的流表，0: node_id, 1: output port, 2: src ip, 3: dst ip, 4: delay
 * 通过匹配源、目的IP字段进行转发
 */
const string IP_RULE_BODY =
R"({{"priority": 40010,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [{{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_SRC","ip": "{2}/32"}},
                    {{"type": "IPV4_DST","ip": "{3}/32"}}
                ]}}
    }})";

const string IP_RULE_BODY_CHANGE_TOS =
R"({{"priority": 40010,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [{{"type": "OUTPUT","port": "{1}"}},{"type": "SET_FIELD", "field": "IPV4_TOS", "value": "{4}"}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_SRC","ip": "{2}/32"}},
                    {{"type": "IPV4_DST","ip": "{3}/32"}}
                ]}}
    }})";


const string IP_RULE_BODY_TIMEOUT =
R"({{"priority": 40011,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {3}}},
                    {{"type": "OUTPUT","port": "{1}"}}
                ]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_SRC","ip": "{2}/32"}},
                    {{"type": "IPV4_DST","ip": "{3}/32"}}
                ]}}
    }})";

const string IP_RULE_BODY_DIS =
R"({{"priority": 40010,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [{{"type": "OUTPUT","port": "{1}"}},{{"type": "OUTPUT","port": "{4}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_SRC","ip": "{2}/32"}},
                    {{"type": "IPV4_DST","ip": "{3}/32"}}
                ]}}
    }})";

const string IP_RULE_BODY_DIS_TIMEOUT =
R"({{"priority": 40011,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {3}}},
                    {{"type": "OUTPUT","port": "{1}"}},
                    {{"type": "OUTPUT","port": "{5}"}}
                ]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_SRC","ip": "{2}/32"}},
                    {{"type": "IPV4_DST","ip": "{3}/32"}}
                ]}}
    }})";



/* 目的节点的流表，0: node_id, 1: local ip address
 * 匹配目的IP地址为本地地址
 */
const string LOCAL_IP_BODY =
R"({{"priority": 40010,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [{{"type": "OUTPUT","port": "LOCAL"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IPV4_DST","ip": "{1}/32"}}
                ]}}
    }})";


/* 目的节点的流表，0: node_id, 1: local mac address
 * 匹配目的MAC地址为本地地址,且以太类型为 IP
 */
const string LOCAL_ETH_BODY =
R"({{"priority": 40010,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [ {{"type": "OUTPUT","port": "LOCAL"}} ]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "ETH_DST","mac": "{1}"}}
                ]}}
    }})";



/* ************************************************************************ */
/* ***************************** 2 MPLS FLOW ****************************** */
/* ************************************************************************ */



/* 起始节点的流表，0: node_id, 1: output port, 2: src mac, 3: dst mac, 4: mpls label, 5: protocol, 6: dscp, 7: ecn, 8: delay
 * 匹配源、目的MAC地址进行转发
 */
const string PUSH_PUSH =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {4}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IP_PROTO","protocol": {5}}},
                    {{"type": "IP_DSCP","ipDscp": {6}}},
                    {{"type": "IP_ECN","ipEcn": {7}}},
                    {{"type": "ETH_SRC","mac": "{2}"}},
                    {{"type": "ETH_DST","mac": "{3}"}}
                ]}}
    }})";

const string PUSH_PUSH_TIMEOUT =
R"({{"priority": 40021,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {8}}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {4}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IP_PROTO","protocol": {5}}},
                    {{"type": "IP_DSCP","ipDscp": {6}}},
                    {{"type": "IP_ECN","ipEcn": {7}}},
                    {{"type": "ETH_SRC","mac": "{2}"}},
                    {{"type": "ETH_DST","mac": "{3}"}}
                ]}}
    }})";

/* 中间节点的流表，0: node_id, 1: output port, 2: mpls label, 3: delay ms
 * 匹配 MPLS label
 */
const string FORWARD_2MPLS =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{2}"}}
                ]}}
    }})";

const string FORWARD_2MPLS_TIMEOUT =
R"({{"priority": 40021,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {3}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{2}"}}
                ]}}
    }})";

/* 目的节点的流表，0: node_id, 1: MPLS label
 * 匹配 MPLS label
 */
const string POP_POP =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x0800"}},
                    {{"type": "OUTPUT","port": "LOCAL"}} ]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{1}"}}
                ]}}
    }})";




/* ************************************************************************ */
/* ***************************** 3 MPLS FLOW ****************************** */
/* ************************************************************************ */



/* 起始节点的流表，0: node_id, 1: output port, 2: src mac, 3: dst mac, 4: mpls label, 5: protocol, 6: dscp, 7: ecn, 8: delay
 * 匹配源、目的MAC地址进行转发
 */
const string PUSH_PUSH_PUSH =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {4}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IP_PROTO","protocol": {5}}},
                    {{"type": "IP_DSCP","ipDscp": {6}}},
                    {{"type": "IP_ECN","ipEcn": {7}}},
                    {{"type": "ETH_SRC","mac": "{2}"}},
                    {{"type": "ETH_DST","mac": "{3}"}}
                ]}}
    }})";

const string PUSH_PUSH_PUSH_TIMEOUT =
R"({{"priority": 40021,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {8}}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {4}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x0800"}},
                    {{"type": "IP_PROTO","protocol": {5}}},
                    {{"type": "IP_DSCP","ipDscp": {6}}},
                    {{"type": "IP_ECN","ipEcn": {7}}},
                    {{"type": "ETH_SRC","mac": "{2}"}},
                    {{"type": "ETH_DST","mac": "{3}"}}
                ]}}
    }})";

/* 中间节点的流表，0: node_id, 1: output port, 2: mpls label, 3: delay ms
 * 匹配 MPLS label
 */
const string FORWARD_3MPLS =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {2}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{2}"}}
                ]}}
    }})";

const string FORWARD_3MPLS_TIMEOUT =
R"({{"priority": 40021,"timeout": 5,"hardTimeout": 1,"isPermanent": false,
    "deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "VLAN_PUSH"}},
                    {{"type": "L2MODIFICATION","subtype": "VLAN_ID","vlanId": {3}}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": 0}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_PUSH","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_LABEL","label": {2}}},
                    {{"type": "OUTPUT","port": "{1}"}}]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{2}"}}
                ]}}
    }})";


/* 目的节点的流表，0: node_id, 1: MPLS label
 * 匹配 MPLS label
 */
const string POP_POP_POP =
R"({{"priority": 40020,"isPermanent": true,"deviceId": "of:000000000000{0}",
    "treatment": {{"instructions": [
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x8847"}},
                    {{"type": "L2MODIFICATION","subtype": "MPLS_POP","ethernetType": "0x0800"}},
                    {{"type": "OUTPUT","port": "LOCAL"}} ]}},
    "selector": {{"criteria": [
                    {{"type": "ETH_TYPE","ethType": "0x8847"}},
                    {{"type": "MPLS_LABEL","label": "{1}"}}
                ]}}
    }})";

} /* namespace rules */

#endif
